# MCP Server工具 - HTTP Stream 类 MCP Server
from pathlib import Path
import os
import asyncio
from dotenv import load_dotenv
from mcp.server.fastmcp import FastMCP
from insight_agent.utils.agent_wise_http_post import inform_insight_thinking, update_insight_result
from insight_agent.utils.agent_generator import AgentGenerator


# ============================ 全局配置 ============================
# 加载环境变量
load_dotenv(override=True)
# 加载Agent所需大模型
llm_model_name = 'deepseek-chat'
# 获取当前文件的目录
current_dir = Path(__file__).resolve().parent
# 加载Agent所需提示词
prompts_file_path = current_dir / 'agent_map_prompt.txt'
# 加载Agent所需工具配置
servers_config_path = current_dir / 'agent_map_servers_config.json'
# 配置线程
thread_config_1 = {"configurable": {"thread_id": "thread1"}}

# 加载Agent生成器
agent_generator = AgentGenerator()
# 初始化 Insight Agent
agent_map_instance = asyncio.run(agent_generator.create_prebuilt_agent(llm_model_name,
                                                                       prompts_file_path,
                                                                       servers_config_path))

# ============================ MCP服务 ============================
# 定义 MCP Server
mcp = FastMCP("agent_map", port=5129)

@mcp.tool()  # 需使用装饰器使 main_agent 可以识别
async def agent_map(user_request):
    '''
    仅当用户提到与“地图、网格、地理位置、区域、地区、地图上的分布、地理位置上的分布”相关的问题时使用本工具
    :param user_request: 用户的相关输入
    :return: 使用本工具的总结回复
    '''
    # ============ 通过 MCP 获取 main_agent 转发的内容 ============
    print(f'💡子智能体 agent_map 通过MCP 收到用户请求：{user_request}')
    # 思维链
    inform_insight_thinking("agent_map", f'好的，用户希望{user_request}')

    # ============ 获取待推送给 main_agent 的 data ============
    sql_query = await generate_sql(user_request)
    print(f'💡子智能体 agent_map 根据用户输入生成了数据查询语句 {sql_query}')
    # 思维链
    inform_insight_thinking("agent_map", f'根据用户输入生成了数据查询语句 {str(sql_query)[:20]}...')

    sql_results = await inquire_data(sql_query)
    print(f'💡子智能体 agent_map 根据数据查询语句得到查询结果 {sql_results}')
    # 思维链
    inform_insight_thinking("agent_map", f'根据数据查询语句得到{len(sql_results)}条查询结果并聚合到网格')

    # ============ 获取待推送给 main_agent 的 data ============
    data_to_post = await format_data(sql_results)
    print(f'💡子智能体 agent_map 将查询结果整理成前端展示接口的形式：{str(data_to_post)[:20]}...')
    # 思维链
    inform_insight_thinking("agent_map", f'将查询结果整理成前端展示接口的形式：{str(data_to_post)[:20]}...')

    # ============ 获取待推送给 main_agent 的 summary ============
    summary_to_post = await generate_summary(data_to_post)
    print(f'💡子智能体 agent_map 根据查询结果生成了数据总结报告 {summary_to_post}')
    # 思维链
    inform_insight_thinking("agent_map", f'根据查询结果生成了数据总结报告：{str(summary_to_post)[:10]}')

    # ============ 汇总 {"summary": summary, "data": data} 形式的信息并 POST 给 main_agent ============
    updated_result = combine_info_to_post(summary_to_post, data_to_post)
    post_response = update_insight_result("agent_map", updated_result)  # 向 insight_result 中更新 agent_map 相关的洞察结果
    print(f'💡子智能体 agent_map 向 main_agent 推送数据获得响应：{post_response}')

    # 通过MCP协议返回文字版洞察报告给 main_agent
    return summary_to_post


async def generate_sql(user_request: str):
    '''
    当用户需要将输入转换为SQL语句时使用
    :param user_request: 需要转换为SQL语句的自然语言输入
    :return:
    '''
    return """
    SELECT STATIS_TIME, PROV, ATTR_GRID_ID, ATTR_GRID_LONG, ATTR_GRID_LAT, COUNT(DISTINCT PERSON_ID) AS USER_COUNT FROM user_insight.insight_general_table WHERE LABEL_IS_GSM = 1 GROUP BY STATIS_TIME, PROV, ATTR_GRID_ID, ATTR_GRID_LAT, ATTR_GRID_LONG LIMIT 200;
    """


async def inquire_data(sql_query: str):
    """
    当用户需要进行数据库查询工作时，请调用该函数。
    该函数用于在指定MySQL服务器上运行一段SQL代码，完成数据查询相关工作，
    并且当前函数是使用pymsql连接MySQL数据库。
    :param sql_query: 字符串形式的SQL查询语句，用于执行对MySQL数据库中insight_general_table表进行查询，并获得相关信息
    :return：sql_query在MySQL中的运行结果。
    """
    # 将结果以 JSON 字符串形式返回
    return (('20250502', '北京', 'G001', 115.3, 40.47, 11), ('20250502', '北京', 'G002', 115.71, 39.88, 25))


async def format_data(sql_results):
    grids_list = []
    data_to_post = {
        "gridsList": grids_list
    }
    for result in sql_results:
        grids_list.append({
            "statisTime": result[0],
            "provId": result[1],
            "gridId": result[2],
            "gridLongitude": result[3],
            "gridLatitude": result[4],
            "gsmCustCount": result[5]
        })
    return data_to_post


async def generate_summary(data_to_post) -> str:
    '''
    根据数据 data_to_post 形成一篇200字的Markdown形式的报告
    :param data_to_post: 转换形式后的MySQL查询结果
    :return: 200字的Markdown形式的报告
    '''
    result = await agent_map_instance.ainvoke(
        {"messages": [{"role": "system",
                       "content": f'''请将“{data_to_post}”总结成一段200字左右的的Markdown形式的报告'''}]},
        thread_config_1
    )
    summary = result['messages'][-1].content
    # 处理 summary
    summary_to_post = summary.replace('markdown', '').replace('```', '')
    return summary_to_post


def combine_info_to_post(summary: str, data: dict):
    updated_result =  {
        "summary": summary,
        "data": data
    }
    return updated_result



if __name__ == "__main__":
    mcp.run(transport="streamable-http")







